package shoot.server.core;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import bullets.Bullet;
import bullets.BulletBoss;
import bullets.BulletEnemy;
import bullets.BulletWing;
import bullets.HeroBullet;
import core.FlyingObject;
import enemy.AirPlane;
import enemy.Bee;
import enemy.BigAirPlane;
import enemy.Enemy;
import enemy.EnemyBoss;
import enemy.Reward;
import enemy.Score;
import hero.Hero;
import hero.UltimateSkill;
import shoot.clientInfo.ShootClientInfo;

public class Server {
	private ServerSocket serverSocket;
	private ShootClientInfo shootInfo;
	private ObjectInputStream ois;
	private ObjectOutputStream oos;
	private int addFire = 40;
	private int bossSpeedx = 4;
	private int enemySpeed = 8;
	private int bulletSpeed = 15;
	private Map<Integer, ObjectInputStream> oisMap = new HashMap<Integer, ObjectInputStream>();
	private Map<Integer, ObjectOutputStream> oosMap = new HashMap<Integer, ObjectOutputStream>();
	public static final int ONE_CLIENT = 1;
	public static final int TWO_CLIENT = 2;

	public Server() {
		try {
			/*
			 * 实例化ServerSocket的同时指定服务端口 如果该端口被系统的其他程序占用，则会抛出异常
			 */
			System.out.println("服务端正在启动......");
			serverSocket = new ServerSocket(8088);
			System.out.println("服务端启动成功");
			shootInfo = new ShootClientInfo();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// 定义定时器间隔时间10毫秒
	private int frequency = 10;
	private int flag = 1;
	public void serverStart() {
		Socket socket = null;
		try {
			for (; flag < 2; flag++) {
				System.out.println("等待一个客户端连接");
				socket = serverSocket.accept();
				System.out.println("客户端连接了");
				// 得到对象输入流
				ois = new ObjectInputStream(socket.getInputStream());
				// 得到对象输出流
				oos = new ObjectOutputStream(socket.getOutputStream());
				shootInfo.getHero().add(new Hero(flag));
				// 把对象流存入集合
				oisMap.put(flag, ois);
				oosMap.put(flag, oos);
				// 完成一次与连接的客户端交互
				writeoos();
				readois();
			}
			//确定游戏状态为运行
			shootInfo.setGameStatus(ShootClientInfo.RUN);
			//发送给客户端
			writeoos();
			// 定时10毫秒运行一次
			Timer timer = new Timer();
			timer.schedule(new TimerTask() {
				@Override
				public void run() {
					try {
						// 判断当前所有飞机的状态，所有的都为Remove时结束游戏
						boolean allHeroIsLive = false;
						for (Hero h : shootInfo.getHero()) {
							if (h.getStatus() != h.getRemove()) {
								allHeroIsLive = true;
							}
						}
						if (allHeroIsLive) {
							readois();//读取客户端信息
							enemyAction();//敌机产生的方法
							bulletAction();//子弹生成的方法
							ultimateSkillAction();//大招生成的方法
							stepAction();//物体移动的方法
							heroBulletCollision();//英雄机子弹碰撞的方法
							wingBulletCollision();//撩机子弹碰撞
							heroCollision();//英雄机碰撞的方法
							ultimateSkillCollision();//大招碰撞的方法
							removeAction();//删除出界和状态为remove的敌机和所有的子弹
							modifyEnemysStatus();//改变敌机的状态
							writeoos();//给客户端发送数据
						} else {
							shootInfo.setGameStatus(ShootClientInfo.GAMEOVER);
							writeoos();
							// timer.cancel();
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}, frequency, frequency);

		} catch (IOException e) {
			System.out.println(e.getMessage());
		}
	}

	public static void main(String[] args) {
		Server server = new Server();
		server.serverStart();
	}

	// 读取客户端的对象流,把各自的英雄机设置好
	public void readois() {
		Hero hero = null;
		for (Integer flag : oisMap.keySet()) {
			try {
				ObjectInputStream ois = oisMap.get(flag);
				Object obj = ois.readObject();
				if (flag == ONE_CLIENT) {
					hero = (Hero) obj;
					if (hero != null && hero.isHasget()) {
						setNewHeroInfo(ONE_CLIENT, hero);
					}
				} else if (flag == TWO_CLIENT) {
					hero = (Hero) obj;
					if (hero != null && hero.isHasget()) {
						setNewHeroInfo(TWO_CLIENT, hero);
					}
				}

			} catch (IOException | ClassNotFoundException e) {
				try {
					ois.close();
					oisMap.remove(flag);
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
	}

	// 根据读回来的客户端不同设置不同的英雄机x和y
	public void setNewHeroInfo(int flag, Hero hero) {
		Hero thisHero = shootInfo.getHeroByFlag(shootInfo.getHero(), flag);
		thisHero.setX(hero.getX());
		thisHero.setY(hero.getY());
		thisHero.setWps(hero.getWps());
		thisHero.setUltimateSkillFlag(hero.isUltimateSkillFlag());
		if (!thisHero.isHasget()) {
			thisHero.setHasget(hero.isHasget());
		}
	}

	// 给客户端写不同的数据
	public void writeoos() {
		for (Integer flag : oosMap.keySet()) {
			try {
				ObjectOutputStream oos = oosMap.get(flag);
				oos.reset();
				oos.writeObject(shootInfo);
				oos.flush();
			} catch (IOException e) {
				try {
					oos.close();
					oosMap.remove(flag);
				} catch (IOException e1) {
					// e1.printStackTrace();
				}
			}
		}
	}

	// 敌机产生的方法
	private int flyIndex = 0;

	public void enemyAction() {
		ArrayList<FlyingObject> enemy = shootInfo.getEnemy();
		ArrayList<Hero> heros = shootInfo.getHero();
		ArrayList<EnemyBoss> enemyBoss = shootInfo.getEnemyBoss();
		flyIndex++;
		if (flyIndex % 30 == 0) {
			Random ran = new Random();
			int enemyAindex = ran.nextInt(20);
			if (enemyAindex < 3) {
				enemy.add(new Bee(enemySpeed));
			} else if (enemyAindex < 15) {
				enemy.add(new AirPlane(enemySpeed));
			} else if (enemyAindex < 20) {
				enemy.add(new BigAirPlane(enemySpeed));
			}			
		}
		for (Hero he : heros) {
			if (he.getScore() % 100 == 0&& he.getScore()!=0 && enemyBoss.size() <= 0) {
				enemyBoss.add(new EnemyBoss(bossSpeedx));
			}

		}
	}

	public void ultimateSkillAction() {
		ArrayList<UltimateSkill> us = shootInfo.getUltimateSkill();
		ArrayList<Hero> heros = shootInfo.getHero();
		for (Hero hero : heros) {
			//System.out.println(heros);
			if (hero.isUltimateSkillFlag()&&us.size()<1) {
				us.add(new UltimateSkill(hero.getX() + hero.getWidth() / 2, hero.getY(), hero.getFlag()));
				System.out.println(us);
				hero.subUltimateSkill();
				hero.setUltimateSkillFlag(false);
			}
		}
	}

	// 飞行物体移动方法
	public void stepAction() {
		shootInfo.getSky().step();
		ArrayList<FlyingObject> enemy = shootInfo.getEnemy();
		ArrayList<HeroBullet> heroHullets = shootInfo.getHeroBullets();
		ArrayList<BulletEnemy> bulletEnemies = shootInfo.getBulletEnemies();
		ArrayList<BulletBoss> bulletBoss = shootInfo.getBulletBoss();
		ArrayList<EnemyBoss> enemyboss = shootInfo.getEnemyBoss();
		ArrayList<UltimateSkill> us = shootInfo.getUltimateSkill();
		ArrayList<BulletWing>  wingBullets= shootInfo.getWingBullets();
		for (int i = 0; i < enemy.size(); i++) {
			usActionStep(enemy.get(i));
		}
		for (HeroBullet b : heroHullets) {
			b.step();
		}
		for (BulletEnemy b : bulletEnemies) {
			usActionStep(b);
		}
		for (EnemyBoss eb : enemyboss) {
			eb.step();
		}
		for (BulletBoss b : bulletBoss) {
			usActionStep(b);
		}
		for (UltimateSkill u : us) {
			u.step();
		}
		for(BulletWing bw:wingBullets) {
			bw.step();
		}
	}

	/*
	 * 大招来的时候的移动方式
	 */
	public void usActionStep(FlyingObject fo) {
		ArrayList<UltimateSkill> us = shootInfo.getUltimateSkill();
		if (us.size() > 0) {
			UltimateSkill u = us.get(0);
			fo.step2(u.getX(), u.getY());
		} else {
			fo.step();
		}

	}

	/*
	 * 把越界的敌机和子弹删除和状态为remove的子弹和敌机删除
	 */
	private void removeAction() {
		ArrayList<FlyingObject> romve = new ArrayList<FlyingObject>();
		ArrayList<FlyingObject> enemys = shootInfo.getEnemy();
//		ArrayList<Bullet> bullets = new ArrayList<>();
//		bullets.addAll(shootInfo.getHeroBullets());
//		bullets.addAll(shootInfo.getBulletBoss());
//		bullets.addAll(shootInfo.getBulletBoss());
//		bullets.addAll(shootInfo.getWingBullets());
		// 删除越界和已经爆炸完的敌机
		for (FlyingObject f : enemys) {
			if (f.outOfBounds() || f.isRemove()) {
				romve.add(f);
			}
		}
		enemys.removeAll(romve);
		romve.clear();
		// 删除越界和已经碰撞的子弹
		removeBullet(shootInfo.getHeroBullets());
		removeBullet(shootInfo.getBulletEnemies());
		removeBullet(shootInfo.getBulletBoss());
		removeBullet(shootInfo.getWingBullets());
		removeEnemyBoss();
		removeUltimateSkill();
	}

	// 删除大招
	public void removeUltimateSkill() {
		ArrayList<UltimateSkill> romve = new ArrayList<>();
		ArrayList<UltimateSkill> us = shootInfo.getUltimateSkill();
		for (UltimateSkill u : us) {
			if (u.isRemove() || u.OutOfBounds()) {
				romve.add(u);
			}
		}
		us.removeAll(romve);
	}

	public void removeBullet(ArrayList<? extends Bullet> bullets) {
		ArrayList<Bullet> romve = new ArrayList<>();
		for (Bullet b : bullets) {
			if (b.outOfBounds() || b.isRemove()) {
				romve.add(b);
			}
		}
		bullets.removeAll(romve);
	}

	public void removeEnemyBoss() {
		ArrayList<EnemyBoss> romve = new ArrayList<>();
		ArrayList<EnemyBoss> enemyBoss = shootInfo.getEnemyBoss();
		for (EnemyBoss eb : enemyBoss) {
			if (eb.isRemove()) {
				romve.add(eb);
			}
		}
		enemyBoss.removeAll(romve);
	}
	/*
	 * 发射子弹
	 */

	private int bulletIndex;

	private void bulletAction() {
		ArrayList<Hero> heros = shootInfo.getHero();
		ArrayList<EnemyBoss> enemyBoss = shootInfo.getEnemyBoss();
		if (bulletIndex % 30 == 0) {
			ArrayList<HeroBullet> bullets = shootInfo.getHeroBullets();
			for (Hero hero : heros) {
				if (hero.getDoubleFire() > 0 && hero.getStatus() == hero.getLive()) {
					bullets.add(new HeroBullet(hero.getX() + hero.getHeroWidth() / 4, hero.getY(), bulletSpeed,hero.getFlag()));
					bullets.add(new HeroBullet(hero.getX() + hero.getHeroWidth() * 3 / 4, hero.getY(), bulletSpeed,hero.getFlag()));
					hero.subtractFire();
				} else if (hero.getStatus() == hero.getLive()) {
					bullets.add(new HeroBullet(hero.getX() + hero.getHeroWidth() / 2-15, hero.getY()-20, bulletSpeed,hero.getFlag()));
				}
				ArrayList<BulletWing>  wingBullets= shootInfo.getWingBullets();
				if(hero.isLife()) {
					int onex=hero.getWps().get(0).getX();
					int oney=hero.getWps().get(0).getY();
					int twox=hero.getWps().get(1).getX();
					int twoY=hero.getWps().get(1).getY();					
					wingBullets.add(new BulletWing(onex,oney,hero.getFlag(),bulletSpeed));
					wingBullets.add(new BulletWing(twox,twoY,hero.getFlag(),bulletSpeed));
				}
			}
		}
		// 敌机发射子弹
		if (bulletIndex % 60 == 0) {
			ArrayList<FlyingObject> enemys = shootInfo.getEnemy();
			ArrayList<BulletEnemy> bulletEnemy = shootInfo.getBulletEnemies();
			for (FlyingObject f : enemys) {
				if (f.isLife()) {
					bulletEnemy.add(((Enemy) f).enemyShoot());
				}
			}
		}
		// boss发射子弹
		if (enemyBoss.size() > 0 && bulletIndex % 90 == 0) {
			ArrayList<BulletBoss> bulletBoss = shootInfo.getBulletBoss();
			for (EnemyBoss eb : enemyBoss) {
				bulletBoss.addAll(eb.enemyBossShoot());
			}
		}
		bulletIndex++;
	}

	/*
	 * 英雄机子弹碰撞,子弹状态改为remove,敌机状态该为dead;
	 */
	public void heroBulletCollision() {
		ArrayList<HeroBullet> bullets = shootInfo.getHeroBullets();
		for (HeroBullet b : bullets) {
			heroBulletEnemyCollision(b);
			heroBulletBossCollision(b);
		}
	}
	public void wingBulletCollision() {
		ArrayList<BulletWing> wingBulles = shootInfo.getWingBullets();
		for (BulletWing b : wingBulles) {
			heroBulletEnemyCollision(b);
			heroBulletBossCollision(b);
		}
	}

	public void ultimateSkillCollision() {
		ArrayList<UltimateSkill> us = shootInfo.getUltimateSkill();
		for (UltimateSkill u : us) {
			heroBulletEnemyCollision(u);
			heroBulletBossCollision(u);
		}
	}

	public void heroBulletEnemyCollision(HeroBullet b) {
		ArrayList<FlyingObject> enemys = shootInfo.getEnemy();
		for (FlyingObject f : enemys) {
			// 判断子弹坐标是否在敌机的范围内，是否发生了碰撞
			boolean xFlag = b.getX() > (f.getX() - b.getWidth()) && b.getX() < (f.getX() + f.getWidth());
			boolean yFlag = b.getY() > (f.getY() - b.getHeight()) && b.getY() < (f.getY() + f.getHeight());
			if (xFlag && yFlag && f.isLife() && b.isLife()) {
				// 如果该敌机是否有奖励类型如果是查看该子弹是那个英雄机的子弹把奖励该它
				Hero hero = getHeroByBullet(b);
				if (f instanceof Reward) {
					if (((Reward) f).getRewaqrdType() > 0) {
						hero.addDoubleFire(addFire);
					} else {
						hero.addLife();
					}
				}
				if (f instanceof Score) {
					hero.addScore(((Score) f).getScore());
				}
				// 如果子弹是大招的话，敌人去死
				if (b instanceof UltimateSkill) {

				} else {
					b.goDead();
				}
				f.goDead();
				break;
			}
		}
	}

	// 英雄机子弹与Boss的碰撞
	public void heroBulletBossCollision(HeroBullet b) {
		ArrayList<EnemyBoss> enemyBoss = shootInfo.getEnemyBoss();
		for (EnemyBoss eb : enemyBoss) {
			boolean xFlag = b.getX() > (eb.getX() - b.getWidth()) && b.getX() < (eb.getX() + eb.getWidth());
			boolean yFlag = b.getY() > (eb.getY() - b.getHeight()) && b.getY() < (eb.getY() + eb.getHeight());
			if (xFlag && yFlag && eb.isLife() && b.isLife()) {
				// 如果该敌机是否有奖励类型如果是查看该子弹是那个英雄机的子弹把奖励该它
				Hero hero = getHeroByBullet(b);
				if (eb.isDead()) {
					hero.addLife();
					hero.addScore(((Score) eb).getScore());
				}
				// 如果子弹是大招的话，boss减命
				if (b instanceof UltimateSkill) {

				} else {
					b.goDead();
				}
				eb.goDead();
				break;
			}
		}
	}

	/*
	 * 敌机子弹是否碰到了英雄机，碰到英雄机减命，子弹状态去死
	 */
	public void enemyBulletCollision(Hero hero) {
		ArrayList<Bullet> bullets = new ArrayList<>();
		bullets.addAll(shootInfo.getBulletEnemies());
		bullets.addAll(shootInfo.getBulletBoss());
		for (Bullet b : bullets) {
			boolean xFlag = b.getX() > (hero.getX() - b.getWidth()) && b.getX() < (hero.getX() + hero.getWidth());
			boolean yFlag = b.getY() > (hero.getY() - b.getHeight()) && b.getY() < (hero.getY() + hero.getHeight());
			if (xFlag && yFlag && b.isLife() && hero.isLife()) {
				hero.subtractLife();
				b.goDead();
				// 敌机状态改为dead
			}

		}
	}

	// 敌机是否碰撞了英雄机
	public void enemyCollision(Hero hero) {
		ArrayList<FlyingObject> enemys = shootInfo.getEnemy();
		for (FlyingObject f : enemys) {
			boolean xFlag = hero.getX() > (f.getX() - hero.getWidth()) && hero.getX() < (f.getX() + f.getWidth());
			boolean yFlag = hero.getY() > (f.getY() - hero.getHeight()) && hero.getY() < (f.getY() + f.getHeight());
			// 判断英雄机是否与敌机撞上
			if (xFlag && yFlag && f.isLife() && hero.isLife()) {
				// 英雄减命
				hero.subtractLife();
				// 敌机状态改为dead
				f.goDead();
				// 敌机如果是蜜蜂的化得奖励
				if (f instanceof Bee) {
					if (((Bee) f).getRewaqrdType() > 0) {
						hero.addDoubleFire(addFire);
					} else {
						hero.addLife();
					}
				}
			}
		}

	}

	/*
	 * 英雄机碰撞敌机和敌机子弹英雄机减命，敌机状态该为dead，敌机子弹去死;
	 */
	public void heroCollision() {

		ArrayList<Hero> heros = shootInfo.getHero();
		for (Hero hero : heros) {
			if (hero.isRemove()) {
				continue;
			}
			enemyBulletCollision(hero);
			enemyCollision(hero);
		}
	}

	// 根据子弹判断该子弹是那个英雄机发射的，返回该英雄机
	public Hero getHeroByBullet(HeroBullet bullet) {
		Hero hero = null;
		for (Hero h : shootInfo.getHero()) {
			if (h.getFlag() == bullet.getHeroFlag()) {
				hero = h;
			}
		}
		return hero;
	}

	public void modifyUltimateSkillIndex() {
		UltimateSkill us = shootInfo.getUltimateSkill().get(0);
		if (us.isLife() && us.getIndex() <= 4) {
			us.indexAddOne();
			if (us.getIndex() == 4) {
				us.setIndex(0);
			}
		}
	}

	// 根据敌机的状态死亡设置爆炸效果，和改变为删除状态
	public void modifyEnemysStatus() {
		for (int i = 0; i < shootInfo.getEnemy().size(); i++) {
			FlyingObject enemy = shootInfo.getEnemy().get(i);
			if (enemy.getStatus() == enemy.getDead()) {
				if (enemy.getIndex() >= 4) {
					enemy.setStatus(enemy.getRemove());
				} else {
					enemy.indexAddOne();
				}
			}
		}
		for (EnemyBoss eb : shootInfo.getEnemyBoss()) {
			if (eb.isDead()) {
				if (eb.getIndex() >= 4) {
					eb.setStatus(eb.getRemove());
				} else {
					eb.indexAddOne();
				}
			}
		}
	}

}
